﻿using System;
using System.Collections.Generic;
using System.Linq;
using MIAP.DataAccess.Interfaces;
using MIAP.DataAccess.SqlServer.Model;
using MIAP.Entidades;
using MIAP.Entidades.Enums;

namespace MIAP.DataAccess.Implementaciones.SQL
{
    /// <summary>
    /// Clase de las operaciones de acceso a datos para él módulo de Solicitud de Recarga de Archivo.
    /// </summary>
    public class SolicitudRecargaArchivoDao : ISolicitudRecargaArchivoDao
    {
        #region Operaciones para la vista SolicitudRecargaArchivo

        /// <summary>
        /// Obtiene todos los archivos que el usuario pueda cargar. 
        /// </summary>
        /// <param name="idProyecto">Es el id del proyecto con el que deberán estar relacionados los archivos.</param>
        /// <param name="idUsuario">Es el id del usuario con el cual deberán estar relacionados los archivos.</param>
        /// <returns>Lista de archivos.</returns>
        public IList<CatalogoInfo> GetArchivosByUsuarioProyecto(int idProyecto, int? idUsuario)
        {
            List<CatalogoInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                             join archivo in context.MIAP_ARCHIVO
                             on usuarioArchivo.ID_ARCHIVO equals archivo.ID_ARCHIVO
                             join proyecto in context.MIAP_PROYECTO
                             on archivo.ID_PROYECTO equals proyecto.ID_PROYECTO
                             join cargaArchivo in context.MIAP_CARGA_ARCHIVO
                             on archivo.ID_ARCHIVO equals cargaArchivo.ID_ARCHIVO
                             join bitacoraCargaArchivo in context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                             on cargaArchivo.ID_CARGA_ARCHIVO equals bitacoraCargaArchivo.ID_CARGA_ARCHIVO
                             join bitacoraGeneral in context.MIAP_BITACORA_GENERAL
                             on bitacoraCargaArchivo.ID_BITACORA_GENERAL equals bitacoraGeneral.ID_BITACORA_GENERAL
                             where ((proyecto.ID_PROYECTO == idProyecto && (!idUsuario.HasValue || usuarioArchivo.ID_USUARIO == idUsuario))
                             && usuarioArchivo.ES_CARGA == true && archivo.ACTIVO
                             && (bitacoraGeneral.ID_ESTATUS_PROCESO == (int)EstatusProceso.Finalizado_Correcto))
                             select new CatalogoInfo
                             {
                                 IdItem = usuarioArchivo.ID_ARCHIVO,
                                 Descripcion = archivo.NOMBRE
                             }).ToList();

                result = query;
            }

            return result;
        }

        /// <summary>
        /// Obtiene los archivos relacionados con el usuario a los que se les puede levantar una solicitud de recarga.
        /// </summary>
        /// <param name="filtroSolicitud">Filtros aplicados a la consulta.</param>        
        /// <returns>Lista de archivos</returns>
        public IList<SolicitudRecargaArchivoInfo> GetArchivosRecarga(SolicitudRecargaArchivoInfo filtroSolicitud)
        {
            List<SolicitudRecargaArchivoInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from cargaArchivo in context.MIAP_CARGA_ARCHIVO
                             join archivo in context.MIAP_ARCHIVO
                             on cargaArchivo.ID_ARCHIVO equals archivo.ID_ARCHIVO
                             join usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                             on archivo.ID_ARCHIVO equals usuarioArchivo.ID_ARCHIVO
                             join bitacoraArchivo in context.MIAP_BITACORA_ARCHIVO
                             on cargaArchivo.ID_ARCHIVO equals bitacoraArchivo.ID_ARCHIVO
                             join bitacoraCargaArchivo in context.MIAP_BITACORA_GENERAL_CARGA_ARCHIVO
                             on cargaArchivo.ID_CARGA_ARCHIVO equals bitacoraCargaArchivo.ID_CARGA_ARCHIVO
                             join bitacoraGeneral in context.MIAP_BITACORA_GENERAL
                             on bitacoraCargaArchivo.ID_BITACORA_GENERAL equals bitacoraGeneral.ID_BITACORA_GENERAL
                             where ((!filtroSolicitud.IdProyecto.HasValue || archivo.ID_PROYECTO == filtroSolicitud.IdProyecto)
                            && (!filtroSolicitud.IdUsuario.HasValue || usuarioArchivo.ID_USUARIO == filtroSolicitud.IdUsuario)
                            && (!filtroSolicitud.IdArchivo.HasValue || usuarioArchivo.ID_ARCHIVO == filtroSolicitud.IdArchivo)
                            && (!filtroSolicitud.Mes.HasValue || cargaArchivo.MES == filtroSolicitud.Mes)
                            && (!filtroSolicitud.Año.HasValue || cargaArchivo.AÑO == filtroSolicitud.Año)
                            && (usuarioArchivo.ES_CARGA == true)
                            && (archivo.ACTIVO == true)
                            && (bitacoraArchivo.MIAP_BITACORA_GENERAL.ID_TIPO_PROCESO == (int)TipoProceso.Carga || bitacoraArchivo.MIAP_BITACORA_GENERAL.ID_TIPO_PROCESO == (int)TipoProceso.Recarga)
                            && (bitacoraArchivo.VERSION == cargaArchivo.VERSION)
                            && (bitacoraGeneral.ID_ESTATUS_PROCESO == (int)EstatusProceso.Finalizado_Correcto))
                             select new SolicitudRecargaArchivoInfo
                             {
                                 IdCargaArchivo = cargaArchivo.ID_CARGA_ARCHIVO,
                                 IdBitacoraGeneral = bitacoraArchivo.ID_BITACORA_GENERAL,
                                 IdUsuario = usuarioArchivo.ID_USUARIO,
                                 IdArchivo = usuarioArchivo.ID_ARCHIVO,
                                 IdProyecto = archivo.ID_PROYECTO,
                                 NombreSolicitante = cargaArchivo.USUARIO_MODIFICACION,
                                 NombreProyecto = archivo.MIAP_PROYECTO.NOMBRE,
                                 NombreArchivo = archivo.NOMBRE,
                                 NombreEjecutorCarga = bitacoraArchivo.USUARIO_ACTUALIZACION,
                                 FechaProceso = bitacoraArchivo.FECHA_ACTUALIZACION,
                                 Año = bitacoraArchivo.MIAP_BITACORA_GENERAL.AÑO,
                                 Mes = bitacoraArchivo.MIAP_BITACORA_GENERAL.MES,
                                 TipoProceso = bitacoraArchivo.MIAP_BITACORA_GENERAL.MIAP_TIPO_PROCESO.NOMBRE,
                                 Version = bitacoraArchivo.VERSION,
                                 VersionValida = cargaArchivo.VERSION_VALIDA == true ? "Si" : "",
                                 IndicadorVersionValida = cargaArchivo.VERSION_VALIDA,
                                 Versionable = archivo.VERSION
                             }).ToList();

                result = query;
            }

            return result;
        }

        /// <summary>
        /// Guarda una solicitud de recarga de archivo.
        /// </summary>
        /// <param name="solicitud">Solicitud que será guardada.</param>
        /// <param name="user">Usuario que ejecuta la operación.</param>
        public void AddSolicitudRecarga(SolicitudRecargaArchivoInfo solicitud, string user)
        {
            using (var context = new MIAPDBEntities())
            {
                MIAP_BITACORA_GENERAL miapBitacoraGeneral = new MIAP_BITACORA_GENERAL()
                {
                    ID_USUARIO = solicitud.IdUsuario.Value,
                    ID_TIPO_PROCESO = (int)TipoProceso.Solicitud,
                    ID_ESTATUS_PROCESO = (int)EstatusProceso.Inicio,
                    AÑO = solicitud.Año.Value,
                    MES = solicitud.Mes.Value,
                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_BITACORA_GENERAL.Add(miapBitacoraGeneral);

                MIAP_BITACORA_ARCHIVO miapBitacoraArchivo = new MIAP_BITACORA_ARCHIVO()
                {
                    ID_BITACORA_GENERAL = miapBitacoraGeneral.ID_BITACORA_GENERAL,
                    ID_ARCHIVO = solicitud.IdArchivo.Value,
                    NOMBRE_ARCHIVO = solicitud.NombreArchivo,
                    VERSION = solicitud.Version,
                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_BITACORA_ARCHIVO.Add(miapBitacoraArchivo);

                MIAP_SOLICITUD miapSolicitud = new MIAP_SOLICITUD()
                {
                    ID_BITACORA_GENERAL = miapBitacoraGeneral.ID_BITACORA_GENERAL,
                    ID_SOLICITANTE = solicitud.IdUsuario.Value,
                    ID_ARCHIVO = solicitud.IdArchivo.Value,
                    ID_ESTATUS_SOLICITUD = (int)EstatusSolicitud.Pendiente,


                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_SOLICITUD.Add(miapSolicitud);

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Obtiene las versiones de los archivos que tienen una solicitud con estatus pendiente o autorizada
        /// </summary>
        /// <returns>Lista de ids de bitácora general.</returns>
        public IList<CatalogoInfo> GetVersionArchivoEnSolicitud()
        {
            List<CatalogoInfo> listVersionesArchivo;

            using (var context = new MIAPDBEntities())
            {
                var query = from solicitud in context.MIAP_SOLICITUD
                            join bitacoraArchivo in context.MIAP_BITACORA_ARCHIVO
                            on solicitud.ID_BITACORA_GENERAL equals bitacoraArchivo.ID_BITACORA_GENERAL
                            where (solicitud.ID_ESTATUS_SOLICITUD == (int)EstatusSolicitud.Autorizada
                            || solicitud.ID_ESTATUS_SOLICITUD == (int)EstatusSolicitud.Pendiente)
                            select new CatalogoInfo
                            {
                                IdItem = bitacoraArchivo.ID_ARCHIVO,
                                Descripcion = bitacoraArchivo.VERSION
                            };

                listVersionesArchivo = query.ToList();
            }

            return listVersionesArchivo;
        }

        #endregion

        #region Operaciones para la vista Atiende Solicitud

        /// <summary>
        /// Obtiene las solicitudes con estatus pendiente.
        /// </summary>
        /// <param name="idAutorizador">Es el id del autorizador por el que se filtrarán los archivos.</param>
        /// <returns>Lista de solicitudes con estatus pendiente</returns>
        public IList<SolicitudRecargaArchivoInfo> GetSolicitudesPendientes(int idAutorizador)
        {
            List<SolicitudRecargaArchivoInfo> result;

            using (var context = new MIAPDBEntities())
            {
                var query = (from usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                             join solicitud in context.MIAP_SOLICITUD
                             on usuarioArchivo.ID_USUARIO equals solicitud.ID_SOLICITANTE
                             join archivo in context.MIAP_ARCHIVO
                             on solicitud.ID_ARCHIVO equals archivo.ID_ARCHIVO
                             join proyecto in context.MIAP_PROYECTO
                             on archivo.ID_PROYECTO equals proyecto.ID_PROYECTO
                             join bitacoraGeneral in context.MIAP_BITACORA_GENERAL
                             on solicitud.ID_BITACORA_GENERAL equals bitacoraGeneral.ID_BITACORA_GENERAL
                             join bitacoraArchivo in context.MIAP_BITACORA_ARCHIVO
                             on bitacoraGeneral.ID_BITACORA_GENERAL equals bitacoraArchivo.ID_BITACORA_GENERAL
                             where solicitud.ID_ESTATUS_SOLICITUD == (int)EstatusSolicitud.Pendiente
                             && usuarioArchivo.ID_USUARIO == idAutorizador
                             && usuarioArchivo.ES_AUTORIZACION == true
                             select new SolicitudRecargaArchivoInfo
                             {
                                 IdSolicitud = solicitud.ID_SOLICITUD,
                                 IdProyecto = proyecto.ID_PROYECTO,
                                 IdUsuario = solicitud.ID_SOLICITANTE,
                                 IdArchivo = solicitud.ID_ARCHIVO,
                                 IdSolicitante = solicitud.ID_SOLICITANTE,
                                 NombreProyecto = proyecto.NOMBRE,
                                 NombreArchivo = archivo.NOMBRE,
                                 Version = bitacoraArchivo.VERSION,
                                 FechaProceso = solicitud.FECHA_CREACION,
                                 Año = bitacoraGeneral.AÑO,
                                 Mes = bitacoraGeneral.MES
                             }).Distinct().ToList();

                result = query;
            }

            return result;
        }

        /// <summary>
        /// Obtiene el nombre del solicitante de la solicitud de recarga de archivo.
        /// </summary>
        /// <param name="listIdsSolicitudes">Lista de ids de solicitudes.</param>
        /// <returns>Lista de ids de slicitudes y sus respectivos solicitantes.</returns>
        public IList<CatalogoInfo> GetNombreSolicitante(List<int> listIdsSolicitudes)
        {
            IList<CatalogoInfo> result = new List<CatalogoInfo>();

            CatalogoInfo solicitante = new CatalogoInfo();

            using (var context = new MIAPDBEntities())
            {
                foreach (int idSolicitud in listIdsSolicitudes)
                {
                    var query = from usuario in context.usp_ObtenDatosUsuarioSistema(null, null)
                                join solicitud in context.MIAP_SOLICITUD
                                on usuario.ID_USUARIO equals solicitud.ID_SOLICITANTE
                                where solicitud.ID_SOLICITUD == idSolicitud
                                select new CatalogoInfo()
                                {
                                    IdItem = solicitud.ID_SOLICITUD,
                                    Descripcion = string.Format("{0}{1}{2}{3}{4}", usuario.Nombre, " ", usuario.ApellidoPaterno, " ", usuario.ApellidoMaterno)
                                };

                    solicitante = query.Single();

                    result.Add(solicitante);
                }
            }

            return result;
        }

        /// <summary>
        /// Obtiene el nombre del usuario que cargo, recargo o versiono el archivo.
        /// </summary>
        /// <param name="listUsuariosVersionadores">Lista de los usuarios que varsionarón  cargaron los archivos.</param>
        /// <returns>Lista con los nombres de los usuarios.</returns>
        public IList<EjecutorInfo> GetNombreVersionador(List<EjecutorInfo> listUsuariosVersionadores)
        {
            usp_ObtenDatosUsuarioSistema_Result versionadorArchivo;

            List<EjecutorInfo> listVersionadores = new List<EjecutorInfo>();

            using (var context = new MIAPDBEntities())
            {
                foreach (EjecutorInfo usuarioVersionador in listUsuariosVersionadores)
                {
                    var query = from versionador in context.usp_ObtenDatosUsuarioSistema(null, null)
                                where (versionador.Usuario == usuarioVersionador.UsuarioEjecutor)
                                select versionador;

                    versionadorArchivo = query.Single();

                    listVersionadores.Add(new EjecutorInfo() { IdArchivo = usuarioVersionador.IdArchivo, VersionArchivo = usuarioVersionador.VersionArchivo, UsuarioEjecutor = usuarioVersionador.UsuarioEjecutor, NombreEjecutor = string.Format("{0}{1}{2}{3}{4}", versionadorArchivo.Nombre, " ", versionadorArchivo.ApellidoPaterno, " ", versionadorArchivo.ApellidoMaterno) });
                }
            }

            return listVersionadores;
        }

        /// <summary>
        /// Modifica el estatus de la solicitud.
        /// </summary>
        /// <param name="solicitud">Es la información de la solicitud que será modificada.</param>
        /// <param name="autorizarSolicitud">Indicador si a solicitud fue autorizada.</param>
        /// <param name="user">Usuario que ejecuta la operación.</param>        
        public void EditEstatusSolicitud(SolicitudRecargaArchivoInfo solicitud, bool autorizarSolicitud, string user)
        {
            using (var context = new MIAPDBEntities())
            {
                MIAP_BITACORA_GENERAL miapBitacoraGeneral = new MIAP_BITACORA_GENERAL()
                {
                    ID_USUARIO = solicitud.IdUsuario.Value,
                    ID_TIPO_PROCESO = (int)TipoProceso.RespuestaSolicitud,
                    ID_ESTATUS_PROCESO = (int)EstatusProceso.Finalizado_Correcto,
                    AÑO = solicitud.Año.Value,
                    MES = solicitud.Mes.Value,
                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_BITACORA_GENERAL.Add(miapBitacoraGeneral);

                MIAP_BITACORA_ARCHIVO miapBitacoraArchivo = new MIAP_BITACORA_ARCHIVO()
                {
                    ID_BITACORA_GENERAL = miapBitacoraGeneral.ID_BITACORA_GENERAL,
                    ID_ARCHIVO = solicitud.IdArchivo.Value,
                    NOMBRE_ARCHIVO = solicitud.NombreArchivo,
                    VERSION = solicitud.Version,
                    USUARIO_CREACION = user,
                    FECHA_CREACION = DateTime.Now,
                    USUARIO_ACTUALIZACION = user,
                    FECHA_ACTUALIZACION = DateTime.Now
                };

                context.MIAP_BITACORA_ARCHIVO.Add(miapBitacoraArchivo);

                MIAP_SOLICITUD miapSolicitud = (from solicitudBD in context.MIAP_SOLICITUD
                                                where solicitudBD.ID_SOLICITUD == solicitud.IdSolicitud
                                                select solicitudBD).Single();

                if (autorizarSolicitud)
                {
                    miapSolicitud.ID_ESTATUS_SOLICITUD = (int)EstatusSolicitud.Autorizada;
                }
                else
                {
                    miapSolicitud.ID_ESTATUS_SOLICITUD = (int)EstatusSolicitud.Rechazada;
                }

                miapSolicitud.ID_AUTORIZADOR = solicitud.IdUsuario.Value;
                miapSolicitud.ID_BITACORA_GENERAL = miapBitacoraGeneral.ID_BITACORA_GENERAL;
                miapSolicitud.COMENTARIOS = solicitud.Comentarios;
                miapSolicitud.USUARIO_ACTUALIZACION = user;
                miapSolicitud.FECHA_ACTUALIZACION = DateTime.Now;

                context.SaveChanges();
            }
        }

        /// <summary>
        /// Obtiene las direcciones de correo de los autorizadores de archivo.
        /// </summary>
        /// <param name="idArchivo">Es el id del archivo.</param>
        /// <returns>Lista de direcciones de correo de los autorizadores del archivo.</returns>
        public IList<string> GetCorreosAutorizadoresByArchivo(int idArchivo)
        {
            IList<string> result;

            using (var context = new MIAPDBEntities())
            {
                var query = from autorizador in context.usp_ObtenDatosUsuarioSistema(null, null)
                            join usuarioArchivo in context.MIAP_USUARIO_ARCHIVO
                            on autorizador.ID_USUARIO equals usuarioArchivo.ID_USUARIO
                            where usuarioArchivo.ES_AUTORIZACION == true
                            select autorizador.Email;

                result = query.ToList();
            }

            return result;
        }
        #endregion
    }
}
